home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////////////////////
- // ATLVCL.CPP - Provides the connective tissue between
- // the ATL framework and VCL components.
- //
- // $Revision: 1.17.4.4 $
- // $Date: 05 Feb 1998 20:22:36 $
- //
- // Copyright (c) 1998 Borland International
- /////////////////////////////////////////////////////////////////////////////
-
- #include <vcl.h>
- #pragma hdrstop
-
- #if !defined(__ATLVCL_H_)
- #include <atl\atlvcl.h>
- #endif
- #include <comconst.hpp>
- #include <axctrls.hpp>
-
- // Variable to store away System's InitProc
- //
- void* SaveInitProc;
-
- // Unlock routine - Handles case of Local Server by posting WM_QUIT message
- //
- LONG TComModule::Unlock()
- {
- LONG result = CComModule::Unlock();
-
- // If there are no more locks on us, if we were launch via Automation and we're an EXE, Quit
- //
- if ((result == 0) && m_bExe)
- {
- TSysCharSet DelimSet;
- DelimSet << '/' << '-';
- if (FindCmdLineSwitch("AUTOMATION", DelimSet, true))
- ::PostThreadMessage(m_ThreadID, WM_QUIT, 0, 0);
- }
- return result;
- }
-
- // Converts a GUID to an AnsiString
- //
- static AnsiString GuidToString(const GUID& guid)
- {
- LPOLESTR P;
- if (::StringFromCLSID(guid, &P) != S_OK)
- return "";
- AnsiString S = P;
- CoTaskMemFree(P);
- return S;
- }
-
- // Helper used by IPersistStreamInit implementation to save component
- //
- void __fastcall SaveVCLComponentToStream(TComponent *vclInstance, LPSTREAM pStream)
- {
- TVclPtr<TOleStream> OleStrm(new TOleStream(_di_IStream(pStream)));
- TVclPtr<TWriter> Writer(new TWriter(OleStrm, 4096));
- Writer->IgnoreChildren = true;
- Writer->WriteDescendent(vclInstance, NULL);
- }
-
-
- // Helper used by IPersistStreamInit implementation to load component
- //
- void __fastcall LoadVCLComponentFromStream(TComponent *vclInstance, LPSTREAM pStream)
- {
- TVclPtr<TOleStream> OleStrm(new TOleStream(_di_IStream(pStream)));
- OleStrm->ReadComponent(vclInstance);
- }
-
-
- // Helper used by framework to create a reflector object
- //
- TWinControl* CreateReflectorWindow(HWND parent, Controls::TControl* Control)
- {
- return new TReflectorWindow(int(parent), Control);
- }
-
-
- static HRESULT UnregisterTypeLibInterfaces(ITypeLib *pTypeLib)
- {
- HRESULT hr = S_OK;
- int cTypeInfo = pTypeLib->GetTypeInfoCount();
- for (int i = 0; i < cTypeInfo; i++)
- {
- TYPEKIND tk;
- hr = pTypeLib->GetTypeInfoType(i, &tk);
- if (SUCCEEDED(hr) && (tk == TKIND_DISPATCH || tk == TKIND_INTERFACE))
- {
- CComPtr<ITypeInfo> pTypeInfo;
- hr = pTypeLib->GetTypeInfo(i, &pTypeInfo);
- if (SUCCEEDED(hr))
- {
- TYPEATTR* pTypeAttr;
- hr = pTypeInfo->GetTypeAttr(&pTypeAttr);
- if (SUCCEEDED(hr))
- {
- // Build key to delete
- //
- AnsiString key("Interface\\");
- key += GuidToString(pTypeAttr->guid);
- pTypeInfo->ReleaseTypeAttr(pTypeAttr);
-
- TComServerRegistrar::NukeRegKey(key);
- }
- pTypeInfo.Release();
- }
- }
- }
- return hr;
- }
-
- // Creates a Registry Key
- //
- void TComServerRegistrar::CreateRegKey(AnsiString keyStr, AnsiString ValueName, AnsiString Value)
- {
- CRegKey key;
- LONG status = key.Create(HKEY_CLASSES_ROOT, keyStr.c_str());
-
- if (status == ERROR_SUCCESS)
- status = key.SetValue(Value.c_str(), ValueName.c_str());
-
- if (status != ERROR_SUCCESS)
- throw EWin32Error(status);
- }
-
- // Deletes a Registry Key
- // NOTE: A quirk of Windows is that under Win95, ::RegDeleteKey also deletes all descendants
- // whereas under NT the subkey to be deleted must not have subkeys.
- //
- void TComServerRegistrar::DeleteRegKey(AnsiString keyStr)
- {
- LONG status = ::RegDeleteKey(HKEY_CLASSES_ROOT, keyStr.c_str());
- if (status != ERROR_SUCCESS)
- throw EWin32Error(status);
- }
-
- // Delete a Registry Key and all subkeys
- //
- void TComServerRegistrar::NukeRegKey(AnsiString keyStr)
- {
- // Open the Key
- //
- CRegKey key;
- key.Attach(HKEY_CLASSES_ROOT);
- LONG status = key.RecurseDeleteKey(keyStr.c_str());
- if (status != ERROR_SUCCESS)
- throw EWin32Error(status);
- }
-
- // Initialize variables required for registering server
- //
- void TComServerRegistrar::Init(void)
- {
- // Retrieve name of this module
- //
- TCHAR szBuffer[MAX_PATH];
- ::GetModuleFileName(_Module.m_hInst, szBuffer, sizeof(szBuffer));
- m_ModuleName = szBuffer;
-
- // Create string with registry key
- //
- m_ClassKey = _T("CLSID\\");
- m_ClassKey += GuidToString(m_ClassID);
-
- // Create string for server type
- //
- if (_Module.m_bExe)
- m_ServerType = _T("\\LocalServer32");
- else
- m_ServerType = _T("\\InprocServer32");
- }
-
- // Registers (or Unregisters) keys of this server
- //
- HRESULT TComServerRegistrar::UpdateRegistry(bool Register)
- {
- if (Register)
- {
- static TCHAR szAutomation[] = _T(" /Automation");
-
- // Create registry entries
- //
- CreateRegKey(m_ClassKey, "", m_Description);
-
- // Make sure we have /Automation on EXE Automation Servers
- //
- if (_Module.m_bExe && _Module.m_bAutomationServer)
- {
- CreateRegKey(m_ClassKey + m_ServerType, "", m_ModuleName + szAutomation);
- }
- else
- {
- CreateRegKey(m_ClassKey + m_ServerType, "", m_ModuleName);
- }
-
- // NOTE: VCL does not support Free Threading model
- // Hence, we're limited to Single or Apartment Threading model.
- //
- #if defined(_ATL_APARTMENT_THREADED)
- CreateRegKey(m_ClassKey + m_ServerType, _T("ThreadingModel"), _T("Apartment"));
- #else
- CreateRegKey(m_ClassKey + m_ServerType, _T("ThreadingModel"), _T("Single"));
- #endif
-
- // Register CLSID/ProgID
- //
- if (!m_ProgID.IsEmpty())
- {
- CreateRegKey(m_ProgID, "", m_Description);
- CreateRegKey(m_ProgID + _T("\\CLSID"), "", GuidToString(m_ClassID));
- CreateRegKey(m_ClassKey + _T("\\ProgID"), "", m_ProgID);
- }
- }
- else
- {
- // Remove registry entries
- //
- if (!m_ProgID.IsEmpty())
- {
- NukeRegKey(m_ClassKey);
- NukeRegKey(m_ProgID);
- }
- }
- return S_OK;
- }
-
- // Registers (or Unregisters) Server with TypeLibrary
- //
- HRESULT TTypedComServerRegistrar::UpdateRegistry(bool Register)
- {
- // Load the Module's type library (assumes TypeLibrary is part of module)
- //
- TComInterface<ITypeLib> pTypeLib;
- HRESULT hres = ::LoadTypeLib(m_ModuleName.c_bstr(), &pTypeLib);
- if (hres != S_OK)
- return hres;
-
- // Retrieve ITypeInfo
- //
- TComInterface<ITypeInfo> pTypeInfo;
- hres = pTypeLib->GetTypeInfoOfGuid(m_ClassID, &pTypeInfo);
- if (!SUCCEEDED(hres))
- return hres;
-
- // Get description
- //
- WideString Description;
- hres = pTypeInfo->GetDocumentation(MEMBERID_NIL, NULL,
- (BSTR*)(&Description), NULL, NULL);
- if (SUCCEEDED(hres))
- m_Description = AnsiString(Description);
-
- // Obtain TLIBATTR for this type library
- //
- TLIBATTR *pTypeAttr;
- hres = pTypeLib->GetLibAttr(&pTypeAttr);
- if (!SUCCEEDED(hres))
- return hres;
-
- // Get type library version number and GUID from TLIBATTR
- //
- WORD wMajor = pTypeAttr->wMajorVerNum;
- WORD wMinor = pTypeAttr->wMinorVerNum;
- /*
- GUID libID = pTypeAttr->guid;
- */
- pTypeLib->ReleaseTLibAttr(pTypeAttr);
-
- if (Register)
- {
- // Make registry entries
- // Call base first when registering
- //
- TComServerRegistrar::UpdateRegistry(Register);
-
- // Create TypeLibrary keys
- //
- TCHAR szBuffer[128];
- wsprintf(szBuffer, _T("%d.%d"), wMajor, wMinor);
-
- AnsiString VersionNum(szBuffer);
- CreateRegKey(m_ClassKey + _T("\\Version"), "", VersionNum);
-
- AnsiString LibIDStr = GuidToString(pTypeAttr->guid);
- CreateRegKey(m_ClassKey + _T("\\Typelib"), "", LibIDStr);
-
- hres = ::RegisterTypeLib(pTypeLib, m_ModuleName, 0);
- }
- else
- {
- // Call base to unregister
- // NOTE: Base class nukes everything under \\CLSID\\<clsid>
- //
- hres = TComServerRegistrar::UpdateRegistry(Register);
- }
- return hres;
- }
-
-
- // Register (or unregisters) Remote data module
- //
- HRESULT TRemoteDataModuleRegistrar::UpdateRegistry(bool bRegister)
- {
- HRESULT hr = TTypedComServerRegistrar::UpdateRegistry(bRegister);
-
- // Code specific to Remote Data Modules
- //
- if (&Forms::UpdateDataModuleRegistry != NULL)
- Forms::UpdateDataModuleRegistry(bRegister, GuidToString(m_ClassID), m_ProgID);
- return hr;
- }
-
-
- // Registers (or Unregisters) ActiveX Control
- //
- HRESULT TAxControlRegistrar::UpdateRegistry(bool Register)
- {
- HRESULT hres;
- if (Register)
- {
- // Call base first when registering
- //
- hres = TTypedComServerRegistrar::UpdateRegistry(Register);
-
- // Make registry entries
- //
- CreateRegKey(m_ClassKey + _T("\\MiscStatus"), "", '0');
- CreateRegKey(m_ClassKey + _T("\\MiscStatus\\1"), "", (int)m_MiscFlags);
- CreateRegKey(m_ClassKey + _T("\\ToolboxBitmap32"), "",
- m_ModuleName + "," + IntToStr(m_BitmapID));
- CreateRegKey(m_ClassKey + _T("\\Control"), "", "");
- CreateRegKey(m_ClassKey + _T("\\Verb"), "", "");
-
- // Register Verbs
- //
- const OLEVERB *pVerb = m_Verbs;
- while (pVerb->lpszVerbName && *pVerb->lpszVerbName)
- {
- AnsiString szKey(m_ClassKey);
- szKey += _T("\\Verb\\");
- szKey += IntToStr(pVerb->lVerb);
-
- AnsiString szVerb= pVerb->lpszVerbName;
- szVerb += ",";
- szVerb += IntToStr(pVerb->fuFlags);
- szVerb += ",";
- szVerb += IntToStr(pVerb->grfAttribs);
-
- CreateRegKey(szKey, "", szVerb);
-
- pVerb++;
- }
- }
- else
- {
- // Call base class to unregister
- // NOTE: Base class removes everything underneath \\CLSID\\<clsid> && \\<progid>\\
- //
- hres = TTypedComServerRegistrar::UpdateRegistry(Register);
- }
- return hres;
- }
-
-
- // AutomationTerminateProc
- //
- // Verifies if a Server was launched with the /Automation switch and warns
- // user of attempt to unload Server currently being automated.
- //
- bool __fastcall AutomationTerminateProc()
- {
- TSysCharSet DelimSet;
- DelimSet << '/' << '-';
- if (FindCmdLineSwitch("AUTOMATION", DelimSet, true))
- {
- return ::MessageBox(0, (Comconst_SNoCloseActiveServer1 + Comconst_SNoCloseActiveServer2).c_str(),
- Comconst_SAutomationWarning.c_str(),
- MB_YESNO|MB_TASKMODAL|MB_ICONWARNING|MB_DEFBUTTON2) == IDYES;
- }
- else
- // If not launched with /Automation, it's fine to unload
- //
- return True;
- }
-
-